package cn.fldong.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 数据库连接工具类，提供数据库连接池和资源释放功能
 */
public class DBUtil {
    // 数据库连接参数
    private static final String URL = "jdbc:mysql://localhost:3306/student_management_system?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "123456";
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
    
    // 连接池配置
    private static final int INIT_CONNECTIONS = 5; // 初始连接数
    private static final int MAX_CONNECTIONS = 20; // 最大连接数
    private static final List<Connection> connectionPool = new LinkedList<>();
    private static final ReentrantLock lock = new ReentrantLock();
    
    static {
        try {
            // 加载数据库驱动
            Class.forName(DRIVER);
            // 初始化连接池
            initConnectionPool();
        } catch (Exception e) {
            System.err.println("数据库初始化失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    /**
     * 初始化连接池
     */
    private static void initConnectionPool() throws SQLException {
        for (int i = 0; i < INIT_CONNECTIONS; i++) {
            connectionPool.add(createConnection());
        }
        System.out.println("数据库连接池初始化完成，初始连接数: " + INIT_CONNECTIONS);
    }
    
    /**
     * 创建新的数据库连接
     */
    private static Connection createConnection() throws SQLException {
        return DriverManager.getConnection(URL, USERNAME, PASSWORD);
    }

    /**
     * 从连接池获取数据库连接
     * @return 数据库连接对象
     * @throws SQLException 数据库连接异常
     */
    public static Connection getConnection() throws SQLException {
        lock.lock();
        try {
            // 如果连接池为空且未达到最大连接数，创建新连接
            if (connectionPool.isEmpty() && connectionPool.size() < MAX_CONNECTIONS) {
                System.out.println("连接池为空，创建新连接");
                return createConnection();
            } 
            // 如果连接池为空且已达到最大连接数，等待
            else if (connectionPool.isEmpty()) {
                System.out.println("连接池已满，等待释放连接...");
                lock.unlock();
                // 简单等待后重试
                Thread.sleep(100);
                lock.lock();
                // 递归调用，再次尝试获取连接
                return getConnection();
            }
            
            // 从连接池获取连接
            Connection conn = connectionPool.remove(0);
            // 检查连接是否有效
            if (conn.isClosed() || !conn.isValid(1)) {
                conn = createConnection();
            }
            return conn;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new SQLException("获取数据库连接时线程被中断", e);
        } finally {
            lock.unlock();
        }
    }
    
    /**
     * 将连接归还到连接池
     * @param conn 数据库连接
     */
    public static void returnConnection(Connection conn) {
        if (conn != null) {
            lock.lock();
            try {
                if (!conn.isClosed()) {
                    connectionPool.add(conn);
                }
            } catch (SQLException e) {
                System.err.println("归还连接到连接池失败: " + e.getMessage());
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 关闭数据库资源
     * @param conn 数据库连接
     * @param stmt Statement对象
     * @param rs 结果集
     */
    public static void closeResources(Connection conn, Statement stmt, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            // 将连接归还到连接池，而不是关闭
            returnConnection(conn);
        } catch (SQLException e) {
            System.err.println("数据库资源关闭失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 关闭数据库资源（无结果集）
     * @param conn 数据库连接
     * @param stmt Statement对象
     */
    public static void closeResources(Connection conn, Statement stmt) {
        closeResources(conn, stmt, null);
    }
    
    /**
     * 获取当前连接池大小
     * @return 连接池中的连接数
     */
    public static int getConnectionPoolSize() {
        lock.lock();
        try {
            return connectionPool.size();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 测试数据库连接
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        try {
            System.out.println("当前连接池大小: " + getConnectionPoolSize());
            Connection conn = getConnection();
            System.out.println("获取连接后连接池大小: " + getConnectionPoolSize());
            if (conn != null) {
                System.out.println("数据库连接成功!");
                closeResources(conn, null);
                System.out.println("归还连接后连接池大小: " + getConnectionPoolSize());
            } else {
                System.out.println("数据库连接失败!");
            }
        } catch (SQLException e) {
            System.err.println("数据库连接测试失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}